<?php

// @formatter:off
/**
 * @file AutoTagger.php
 * @author Alejandro Dario Simi
 * @date $Date: 2014-05-04 01:33:52 +0000 (Sun, 04 May 2014) $
 *
 * $Id: AutoTagger.php 111 2014-05-04 01:33:52Z daemonraco@gmail.com $
 * $URL: http://wcomix.googlecode.com/svn/trunk/extensions/AutoTagger/includes/AutoTagger.php $
 */
// @formatter:on

class AutoTagger extends WCSingleton {
	/**
	 * @var WCConnection Pointer to the global connection object.
	 */
	protected $_db = null;
	/**
	 * @var string Shortcut to database tables prefixes.
	 */
	protected $_dbprefix = "";
	//
	// Public methods.
	public function cleanDeads() {
		//
		// @{
		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__;
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "delete from  {$this->_dbprefix}autotagger\n";
			$query .= "where        ato_directory not in (\n";
			$query .= "                     select dir_id\n";
			$query .= "                     from   {$this->_dbprefix}directories\n";
			$query .= "                     where  dir_group = ato_group\n";
			$query .= "                      and   dir_lost  = 'N')\n";
			$query .= " or          ato_tag not in (\n";
			$query .= "                     select tag_id\n";
			$query .= "                     from   {$this->_dbprefix}tags\n";
			$query .= "                     where  tag_group = ato_group)\n";

			$stmt = $this->_db->prepare($stmtId, $query);
		}
		// @}

		$stmt->execute();
	}
	public function directoryTags(WCDirectory &$directory) {
		$out = array();

		//
		// @{
		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__;
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "select  *\n";
			$query .= "from    {$this->_dbprefix}autotagger\n";
			$query .= "where   ato_group     = :group\n";
			$query .= " and    ato_directory = :directory\n";

			$stmt = $this->_db->prepare($stmtId, $query);
		}
		// @}

		$params = array(
			":group" => $directory->group,
			":directory" => $directory->id
		);

		$holder = WCTagsHolder::I();
		if($stmt->execute($params)) {
			foreach($stmt->fetchAll() as $row) {
				$tag = $holder->item($row["ato_tag"]);
				if($tag && $tag->ok()) {
					$out[$tag->id] = $tag;
				}
			}
		}

		return $out;
	}
	public function runCron(WCGroup &$group, $spacer = "", $verbose = true) {
		$this->cleanDeads();
		//
		// Query to load associations @{
		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__;
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "select  *\n";
			$query .= "from    {$this->_dbprefix}autotagger\n";
			$query .= "where   ato_group = :group\n";
			$query .= "order by ato_directory asc\n";

			$stmt = $this->_db->prepare($stmtId, $query);
		}
		// @}

		$params = array(
			":group" => $group->id
		);

		echo "{$spacer}Checking group {$group}:".($verbose ? "\n" : "");

		$dirHolder = WCDirectoriesHolder::I();
		$tagHolder = WCTagsHolder::I();
		if($stmt->execute($params) && $stmt->rowCount() > 0) {
			echo ($verbose ? "" : " ");
			$dir = false;
			foreach($stmt->fetchAll() as $row) {
				if(!$dir || $dir->id != $row["ato_directory"]) {
					$dir = $dirHolder->item($row["ato_directory"]);
					if($dir && $dir->ok() && $dir->group == $group->id) {
						echo ($verbose ? "{$spacer}\tAutotagging directory {$dir}:\n" : "");
					} else {
						continue;
					}
				}
				$tag = $tagHolder->item($row["ato_tag"]);
				if($dir && $tag && $dir->ok() && $tag->ok() && $dir->group == $tag->group) {
					echo ($verbose ? "{$spacer}\t\tAdding tag {$tag}: " : "");

					if($tag->addDirectory($dir)) {
						echo ($verbose ? WCColorText::ShellGreen("Done\n") : ".");
					} else {
						echo ($verbose ? WCColorText::ShellRed("Failed\n") : "?");
					}
				}
			}
		}
		echo ($verbose ? "" : WCColorText::ShellGreen(" Done\n") );

		$this->optimizeTables(true, $spacer);
	}
	public function updateDirectory(WCDirectory &$directory, $tags = array()) {
		$this->clearDirectory($directory);

		if($directory->ok()) {
			$group = $directory->group();
			foreach($this->namesToTags($tags, $group) as $tag) {
				$this->associate($directory, $tag);
			}
		}
	}
	//
	// Protected methods.
	protected function associate(WCDirectory &$directory, WCTag &$tag) {
		//
		// @{
		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__;
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "insert\n";
			$query .= "        into {$this->_dbprefix}autotagger(\n";
			$query .= "                ato_group, ato_directory, ato_tag, ato_description)\n";
			$query .= "        values(:group, :directory, :tag, :description)\n";

			$stmt = $this->_db->prepare($stmtId, $query);
		}
		// @}

		$params = array(
			":group" => $directory->group,
			":directory" => $directory->id,
			":tag" => $tag->id,
			":description" => "'{$directory}' -> '{$tag}'"
		);

		$stmt->execute($params);
	}
	protected function clearDirectory(WCDirectory &$directory) {
		//
		// @{
		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__;
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "delete from {$this->_dbprefix}autotagger\n";
			$query .= "where       ato_directory = :directory\n";

			$stmt = $this->_db->prepare($stmtId, $query);
		}
		// @}

		$stmt->execute(array(":directory" => $directory->id));

		WCViewManager::I()->invalidate(WCViewManager::KeyDirectory, $directory->id);
	}
	protected function init() {
		//
		// Loading shortcuts.
		// @{
		$this->_db = WCConnection::Instance();
		$this->_dbprefix = $this->_db->prefix();
		// @}
	}
	protected function namesToTags($tags, WCGroup &$group) {
		$out = array();

		$holder = WCTagsHolder::I();
		foreach($tags as $name) {
			$tag = $holder->itemByNameInGroupCI($name, $group);
			$tag = array_shift($tag);
			if($tag && $tag->ok()) {
				$out[] = $tag;
			}
		}

		return $out;
	}
	protected function optimizeTables($isCron, $spacer) {
		//
		// Creating the statement to optimize a table.
		// @{
		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__;
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "optimize table {$this->_dbprefix}autotagger\n";

			$stmt = $this->_db->prepare($stmtId, $query);
		}
		// @}

		$stmt->execute();
	}
}
